import {
  forwardRef,
  type MouseEventHandler,
  useImperativeHandle,
  useRef,
  useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import classNames from 'classnames'
import { isPromise } from '@/library/tool-kits/is-valid'
import { withNativeProps } from '../../utils/native-props'
import { DotLoading } from '../DotLoading'
import type {
  ButtonRef,
  ButtonProps,
} from './type'

const classPrefix = 'rt-button'

export const Button = forwardRef<ButtonRef, ButtonProps>((props, ref) => {
  const { t } = useTranslation()
  const {
    block = false,
    fill = 'solid',
    loading = false,
    loadingText = '',
    loadingIcon = <DotLoading color="#aaa" />,
    disabled = false,
    onClick,
    pattern = 'default',
    shape = 'default',
    type = 'button',
    children = t('common.gallery.Button.submitText'),
  } = props
  const nativeButtonRef = useRef<HTMLButtonElement>(null)
  const [innerLoading, setInnerLoading] = useState(false)
  const actLoading = loading === 'auto' ? innerLoading : loading
  const actDisabled = disabled || actLoading

  const onInnerClick: MouseEventHandler<HTMLButtonElement> = async (e) => {
    if (!onClick) return

    const promise = onClick(e as any)

    if (isPromise(promise)) {
      try {
        setInnerLoading(true)
        await promise
        setInnerLoading(false)
      } catch (err) {
        setInnerLoading(false)
        throw err
      }
    }
  }

  useImperativeHandle(ref, () => ({
    get nativeElement() {
      return nativeButtonRef.current
    },
  }))

  return withNativeProps(
    props,
    <button
      ref={nativeButtonRef}
      // eslint-disable-next-line react/button-has-type
      type={type}
      disabled={actDisabled}
      onClick={onInnerClick}
      className={classNames(
        classPrefix,
        actDisabled && `${classPrefix}-disabled`,
        block && `${classPrefix}-block`,
        `${classPrefix}-${pattern}`,
        `${classPrefix}-fill-${fill}`,
        `${classPrefix}-shape-${shape}`,
      )}
      onMouseDown={props.onMouseDown}
      onMouseUp={props.onMouseUp}
      onTouchStart={props.onTouchStart}
      onTouchEnd={props.onTouchEnd}
    >
      {actLoading ? (
        <div className={`${classPrefix}-loading-wrapper`}>
          {loadingIcon}
          {loadingText}
        </div>
      ) : (
        <span>{children}</span>
      )}
    </button>,
  )
})
